package com.wasion.gydpe.ice;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import CommProxy.CBasicParameter;
import CommProxy.CommRegisterPrx;
import CommProxy.CommRegisterPrxHelper;
import CommProxy.IWriteablePrx;
import CommProxy.IWriteablePrxHelper;
import CommProxy.NodeInfo;
import CommProxy.RegisterStep;
import Ice.ObjectPrx;

class Sequence {

	public static final int NULL_SEQUENCE_ID = 0;
	public static final int MAX_SEQUENCE = 1024 * 1024;
	public static final int MIN_SEQUENCE = 1;

	private static int s_seq = MIN_SEQUENCE;

	public static synchronized int get() {
		if (!(s_seq < MAX_SEQUENCE)) // 超出最大序列号
		{
			s_seq = MIN_SEQUENCE;
		}
		return s_seq++;
	}
};

class TransProxy {

	public String param;
	public IWriteablePrx prx;

	public TransProxy(String aParam, IWriteablePrx aProxy) {
		param = aParam;
		prx = aProxy;
	}
};

class CRemotePeerExpNotify implements ICommExpNotify {

	private CSinglePeer _session;

	public CRemotePeerExpNotify(CSinglePeer session) {
		_session = session;
	}

	public void OnExpNotify(ObjectPrx remotePrx, short state) {
		if (state == STATE_ON) // 通讯从断开到连接
		{
			_session.reg(_session.getNode(), RegisterStep.rsEnd);
		}
	}
};

public class CSinglePeer {
	private static final int WAIT_TRANS_SECONDS = 10 * 60; // 10分钟
	private static final String HEART_BEAT_NAME = "heartBeat";

	protected IceWrapper _iceWrapper;
	protected IWriteablePrx _proxy; // 输出代理
	protected String _remotePeerName; // 输出代理名称
	protected CommRegisterPrx _reg; // 注册代理
	protected String _remoteRegName; // 注册代理名称
	protected CInputChannel _input; // 接收输入服务
	protected String _localPeerName; // 接收输入服务名称
	protected NodeInfo _node; // 本地向远端进行注册的信息
	Lock _mutex;
	Condition _received_answer;
	int _revId; // 当前收到报文的序号，需要同步

	protected class TransRet {
		IWriteablePrx proxy;
		int result;
	}

	protected class RegRet {
		CommRegisterPrx proxy;
		int result;
	}

	public Ice.Communicator getCommunicator() {
		return _iceWrapper.getCommunicator();
	}

	// 设置发送代理
	public void setTransProxy(IWriteablePrx proxy) {
		_proxy = proxy;
	}

	public IceWrapper getIceWrapper() {
		return _iceWrapper;
	}

	public NodeInfo getNode() {
		return _node;
	}

	// “trans”方法中用到的辅助方法
	// 此方法的调用者负责同步
	private boolean isEqual(int seqId) {
		return seqId == _revId;
	}

	public CSinglePeer() {
	}

	public CSinglePeer(IceWrapper iceWrapper) {
		_iceWrapper = iceWrapper;
		_revId = Sequence.NULL_SEQUENCE_ID;
		_mutex = new ReentrantLock();
		_received_answer = _mutex.newCondition();
	}

	public TransRet stringToTransProxy(String param, boolean needCheck) {
		TransRet ret = new TransRet();
		if (param != null) {
			try {
				ret.proxy = needCheck ? IWriteablePrxHelper
						.checkedCast(_iceWrapper.createProxy(param))
						: IWriteablePrxHelper.uncheckedCast(_iceWrapper
								.createProxy(param));
			} catch (Exception e) {
				ret.proxy = null;
				ret.result = CCustomReceiver.CP_NO_PROXY;
				return ret;
			}

			if (ret.proxy != null) {
				ret.result = CCustomReceiver.CP_OK;
				return ret;
			} else {
				// 远端代理为空
				ret.proxy = null;
				ret.result = CCustomReceiver.CP_NO_PROXY;
				return ret;
			}
		} else {
			// 无远端代理初始化参数
			ret.proxy = null;
			ret.result = CCustomReceiver.CP_NO_INIT_PRAM;
			return ret;
		}
	}

	public RegRet stringToRegProxy(String param, boolean needCheck) {
		RegRet ret = new RegRet();
		if (param != null) {
			try {
				ret.proxy = needCheck ? CommRegisterPrxHelper
						.checkedCast(_iceWrapper.createProxy(param))
						: CommRegisterPrxHelper.uncheckedCast(_iceWrapper
								.createProxy(param));
			} catch (Exception e) {
				ret.proxy = null;
				ret.result = CCustomReceiver.CP_NO_PROXY;
				return ret;
			}

			if (ret.proxy != null) {
				ret.result = CCustomReceiver.CP_OK;
				return ret;
			} else {
				// 远端代理为空
				ret.proxy = null;
				ret.result = CCustomReceiver.CP_NO_PROXY;
				return ret;
			}
		} else {
			// 无远端代理初始化参数
			ret.proxy = null;
			ret.result = CCustomReceiver.CP_NO_INIT_PRAM;
			return ret;
		}
	}

	protected String getFrameSender() {
		return _localPeerName;
	}

	// 注册
	public int registerNode(NodeInfo node, RegisterStep step,
			CommRegisterPrx proxy) {
		// 使用代理进行实际注册工作
		try {
			proxy.reg(node, step);
		} catch (Exception e) {
			// 通过注册代理注册节点失败
			return CCustomReceiver.CP_ICE_EXCEPTION;
		}

		return CCustomReceiver.CP_OK;
	}

	public int reg(NodeInfo node, RegisterStep step) {
		if (null == _reg) {// 无代理，则先构造
			RegRet r = stringToRegProxy(_remoteRegName, true);
			_reg = r.proxy;
			if (r.result != CCustomReceiver.CP_OK) {// 构造错误，返回构造时候的错误代码
				return r.result;
			}
		}

		int ret = registerNode(node, step, _reg); // 注册
		if (ret == CCustomReceiver.CP_ICE_EXCEPTION) {// 使用ice底层发送的时候抛出异常
			// 重新构造代理再发一次
			RegRet r = stringToRegProxy(_remoteRegName, true);
			_reg = r.proxy;
			if (r.result == CCustomReceiver.CP_OK) {// 构造成功
				ret = registerNode(node, step, _reg); // 重新注册
			}
		}

		return ret;
	}

	// 发送信息的序号（seqID）在发送前一般不要设置，此方法会自动处
	// 理。但如果此函数的调用者需要用来记录发送的信息，可在发送前
	// 设置为大于（注意不能等于）“MAX_SEQUENCE”的值，
	// “MAX_SEQUENCE”在class Sequence中定义。
	public int send(CBasicParameter frame, boolean isWait, IWriteablePrx proxy) {
		int ret = CCustomReceiver.CP_UNKNOWN_ERROR;

		// 设置报文相关信息
		if (frame.seqID == Sequence.NULL_SEQUENCE_ID) // 没设置序号
		{
			frame.seqID = Sequence.get(); // 自动设置
		}
		frame.isWait = isWait;
		String sender = getFrameSender();
		if (sender != null) // 取到发送者
		{
			frame.sender = sender;
		}

		// 发送
		try {
			ret = proxy.trans(frame);
		} catch (Exception e) {
			// 使用代理 发送失败
			return CCustomReceiver.CP_ICE_EXCEPTION;
		}

		// 阻塞方式，等待结果返回
		if ((ret == CCustomReceiver.CP_OK) && isWait) {
			_mutex.lock();
			try {
				int seqId = frame.seqID; // 记录等待的报文的序号

				while ((!isEqual(seqId))
						&& (_received_answer.await(WAIT_TRANS_SECONDS,
								TimeUnit.SECONDS))) {
					// 没操作
				}

				if (isEqual(seqId)) {
					_revId = Sequence.NULL_SEQUENCE_ID; // 更新，表示接收完成，当前暂无报文
				} else {
					ret = CCustomReceiver.CP_WAIT_TIMEOUT;
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				_mutex.unlock();
			}
		}
		// 存入历史
		FrameHistory.add(frame);
		return ret;
	}

	public TransRet send(CBasicParameter frame, boolean isWait,
			TransProxy aProxy) {
		TransRet ret = new TransRet();
		ret.proxy = aProxy.prx;

		if (aProxy.prx == null) {// 无代理，则先构造
			ret = stringToTransProxy(aProxy.param, true);
			if (ret.result != CCustomReceiver.CP_OK) {// 构造错误，返回构造时候的错误代码
				return ret;
			}
		}

		ret.result = send(frame, isWait, ret.proxy); // 发送
		if (ret.result == CCustomReceiver.CP_ICE_EXCEPTION) {// 使用ice底层发送的时候抛出异常
			// 重新构造代理再发一次
			ret = stringToTransProxy(aProxy.param, true);
			if (ret.result == CCustomReceiver.CP_OK) {// 构造成功
				ret.result = send(frame, isWait, ret.proxy); // 重发
			}
		}

		return ret;
	}

	public int trans(CBasicParameter frame, boolean isWait) {
		TransRet ret = send(frame, isWait, new TransProxy(_remotePeerName,
				_proxy));
		_proxy = ret.proxy;
		return ret.result;
	}

	public void init(String servantName, CCustomReceiver recvHandler,
			String remotePeerName, String remotePeerRegName, String kind) {

		init(servantName, recvHandler, remotePeerName, remotePeerRegName, kind,
				null);
	}

	public void init(String servantName, CCustomReceiver recvHandler,
			String remotePeerName, String remotePeerRegName) {

		init(servantName, recvHandler, remotePeerName, remotePeerRegName, null,
				null);
	}

	public void init(String servantName, CCustomReceiver recvHandler,
			String remotePeerName) {

		init(servantName, recvHandler, remotePeerName, null, null, null);
	}

	public void init(String servantName, CCustomReceiver recvHandler) {

		init(servantName, recvHandler, null, null, null, null);
	}

	public void init(String servantName, CCustomReceiver recvHandler,
			String remotePeerName, String remotePeerRegName, String kind,
			String msgId) {
		assert (_iceWrapper.getAdapter() != null);
		_input = new CInputChannel(servantName, recvHandler);
		_input.setSinglePeer(this);

		_localPeerName = _iceWrapper.getCommunicator().proxyToString(
				_iceWrapper.getAdapter().add(
						_input,
						_iceWrapper.getCommunicator().stringToIdentity(
								servantName)));

		String proxyString = "";
		TestProperties ec = TestProperties.getInstance();
		if (ec != null) {
			proxyString = ec.getPropertyValue("/IceComm.properties",
					"Remote.Proxy");
		}

		if (remotePeerName != null) {

			Ice.ObjectPrx prx = _iceWrapper.createProxy(proxyString, false);
			_remotePeerName = _iceWrapper.getCommunicator().proxyToString(prx);
			try {
				_proxy = IWriteablePrxHelper.checkedCast(prx);
			} catch (Exception e) {
				// 远端数据发送代理 初始化失败
				_proxy = null;
			}
		}

		if (remotePeerRegName != null) {
			Ice.ObjectPrx prx = _iceWrapper.createProxy(proxyString, false);
			_remoteRegName = _iceWrapper.getCommunicator().proxyToString(prx);
			try {
				_reg = CommRegisterPrxHelper.checkedCast(prx);
			} catch (Exception e) {
				// 远端注册代理 初始化失败");
				_reg = null;
			}

			ICommExpNotify notify = new CRemotePeerExpNotify(this);

			// 先验证一下_reg是为了避免在“reg”方法中再去尝试初始化一遍
			// 不可能成功的初始化
			if ((_proxy != null) && (_reg != null)) {
				// 初始化注册用的节点信息
				_node = new NodeInfo();
				_node.ident = _localPeerName;
				_node.msgID = msgId;
				_node.nodeKind = kind;

				if (CCustomReceiver.CP_OK == reg(_node, RegisterStep.rsEnd)) // 注册成功
				{// 远端发送服务连接成功且注册到远端成功
					_iceWrapper.addProxyWithNotify(HEART_BEAT_NAME, _proxy,
							notify, ICommExpNotify.STATE_ON);
				} else {
					_iceWrapper.addProxyWithNotify(HEART_BEAT_NAME, _proxy,
							notify, ICommExpNotify.STATE_OFF);
				}
			} else if (_remotePeerName != null) {
				_iceWrapper.addProxyWithNotify(HEART_BEAT_NAME,
						_remotePeerName, notify, ICommExpNotify.STATE_OFF);
			}
		}
	}

	protected int send(CBasicParameter frame, boolean isWait, Object user,
			IWriteablePrx proxy) {
		int ret = CCustomReceiver.CP_UNKNOWN_ERROR;

		// 设置报文相关信息
		if (frame.seqID == Sequence.NULL_SEQUENCE_ID) // 没设置序号
		{
			frame.seqID = Sequence.get(); // 自动设置
		}
		frame.isWait = isWait;
		String sender = getFrameSender();
		if (sender != null) // 取到发送者
		{
			frame.sender = sender;
		}

		// 发送
		try {
			ret = proxy.trans(frame);
		} catch (Exception e) {
			// 使用代理 发送失败
			return CCustomReceiver.CP_ICE_EXCEPTION;
		}

		// 阻塞方式，等待结果返回
		if ((ret == CCustomReceiver.CP_OK) && isWait) {
			_mutex.lock();
			try {
				int seqId = frame.seqID; // 记录等待的报文的序号

				while ((!isEqual(seqId))
						&& (_received_answer.await(WAIT_TRANS_SECONDS,
								TimeUnit.SECONDS))) {
					// 没操作
				}

				if (isEqual(seqId)) {
					_revId = Sequence.NULL_SEQUENCE_ID; // 更新，表示接收完成，当前暂无报文
				} else {
					ret = CCustomReceiver.CP_WAIT_TIMEOUT;
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				_mutex.unlock();
			}
		}
		// 存入历史
		FrameHistory.add(frame);
		CommDataOwnerInitializer.addFrame(user, frame.seqID);
		return ret;
	}

	public int trans(CBasicParameter frame, boolean isWait, Object user) {
		TransRet ret = send(frame, isWait, user, new TransProxy(
				_remotePeerName, _proxy));
		_proxy = ret.proxy;
		return ret.result;
	}

	private TransRet send(CBasicParameter frame, boolean isWait, Object user,
			TransProxy aProxy) {
		TransRet ret = new TransRet();
		ret.proxy = aProxy.prx;

		if (aProxy.prx == null) {// 无代理，则先构造
			ret = stringToTransProxy(aProxy.param, true);
			if (ret.result != CCustomReceiver.CP_OK) {// 构造错误，返回构造时候的错误代码
				return ret;
			}
		}

		ret.result = send(frame, isWait, user, ret.proxy); // 发送
		if (ret.result == CCustomReceiver.CP_ICE_EXCEPTION) {// 使用ice底层发送的时候抛出异常
			// 重新构造代理再发一次
			ret = stringToTransProxy(aProxy.param, true);
			if (ret.result == CCustomReceiver.CP_OK) {// 构造成功
				ret.result = send(frame, isWait, ret.proxy); // 重发
			}
		}

		return ret;
	}
}